package ac.beiwo.baas.admin.service;

import ac.beiwo.baas.admin.entity.Clazz;
import ac.beiwo.baas.admin.entity.Field;
import ac.beiwo.baas.admin.repository.FieldRepository;
import ac.beiwo.baas.common.entity.SimpleError;
import ac.beiwo.baas.common.entity.SimpleCode;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by Staryet on 15/6/20.
 */
@Service
public class FieldService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ClazzService clazzService;
    @Autowired
    private FieldRepository fieldRepository;

    public void insert(String clazzName, Field field) throws SimpleError {
        String name = field.getName();
        if (StringUtils.isEmpty(name)) {
            throw new SimpleError(SimpleCode.FIELD_NAME_MISSING);
        }
        //保留字禁止作为字段名、验证字段拼写是否合法
        if (name.equals("id") || name.equals("createdAt") || name.equals("updatedAt") || name.equals("ACL") || !isNameValid(name)) {
            throw new SimpleError(SimpleCode.FIELD_NAME_ERROR);
        }
        Clazz clazz = clazzService.get(clazzName);
        field.setClazz(clazz);
        Field exist = fieldRepository.findByClazzAndName(clazz, name);
        if (exist != null) {
            throw new SimpleError(SimpleCode.FIELD_ALREADY_EXIST);
        }
        field.setId(null);
        fieldRepository.insert(field);
        deleteFieldsCache(clazzName);
    }

    public void delete(String clazzName, String name) throws SimpleError {
        Field field = get(clazzName, name);
        if (field.isInternal()) {
            //内建字段禁止删除
            throw new SimpleError(SimpleCode.FIELD_INTERNAL);
        }
        fieldRepository.delete(field);
        deleteFieldsCache(clazzName);
    }

    public long deleteAll(String clazzName) throws SimpleError {
        Clazz clazz = clazzService.get(clazzName);
        deleteFieldsCache(clazzName);
        return fieldRepository.deleteByClazz(clazz);
    }

    public Field get(String clazzName, String name) throws SimpleError {
        Clazz clazz = clazzService.get(clazzName);
        Field field = fieldRepository.findByClazzAndName(clazz, name);
        if (field == null) {
            throw new SimpleError(SimpleCode.FIELD_NOT_FOUND);
        }
        return field;
    }

    public List<Field> list(String clazzName) throws SimpleError {
        List<Field> fields = getFieldsCache(clazzName);
        if (fields == null) {
            //未找到缓存
            Clazz clazz = clazzService.get(clazzName);
            fields = fieldRepository.findByClazzId(clazz.getId());
            setFieldsCache(clazzName, fields);
        }
        return fields;
    }

    public boolean isNameValid(String name) {
        String regex = "^[a-zA-Z][a-zA-Z0-9_]*$";
        return Pattern.matches(regex, name);
    }

    private List<Field> getFieldsCache(String name) {
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        String string = ops.get("_Fields_" + name);
        return JSON.parseArray(string, Field.class);
    }

    private void setFieldsCache(String name, List<Field> fields) {
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        ops.set("_Fields_" + name, JSON.toJSONString(fields));
    }

    private void deleteFieldsCache(String name) {
        redisTemplate.delete("_Fields_" + name);
    }

}
